﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FM_Const
{
    public static readonly int DEFAULT_EXTRA_PADDING = 5;

    // Notes
    public static readonly string _1Note = "\ue0a2";
    public static readonly string _2Note_up = "\ue1d3";
    public static readonly string _2Note_down = "\ue1d4";
    public static readonly string _4Note_up = "\ue1D5";
    public static readonly string _4Note_down = "\ue1d6";
    public static readonly string _8Note_up = "\ue1d7";
    public static readonly string _8Note_down = "\ue1d8";
    public static readonly string _16Note_up = "\ue1d9";
    public static readonly string _16Note_down = "\ue1da";
    public static readonly string _32Note_up = "\ue1db";
    public static readonly string _32Note_down = "\ue1dc";
    public static readonly string FillNote = "\ue1af";
    public static readonly string EmptyNote = "\ue1b0";

    // Clefs
    public static readonly string TrebleClef = "\uD834\uDD1E";
    public static readonly string BassClef = "\uD834\uDD22";

    // Parenthesis
    public static readonly string ParenthesisLeft = "\ue092";
    public static readonly string ParenthesisRight = "\ue093";

    // Brackets
    public static readonly string Bracket = "\ue000";

    // Numbers
    public static readonly string _2 = "\ue082";
    public static readonly string _3 = "\ue083";
    public static readonly string _4 = "\ue084";
    public static readonly string _5 = "\ue085";
    public static readonly string _6 = "\ue086";
    public static readonly string _7 = "\ue087";
    public static readonly string _8 = "\ue088";
    public static readonly string _9 = "\ue089";
    public static readonly string _2_b = "\ue927";
    public static readonly string _3_b = "\ue928";
    public static readonly string _4_b = "\ue929";
    public static readonly string _3_small = "\uea54";
    public static readonly string _5_small = "\uea57";

    // Accidentals
    public static readonly string Flat = "\ue260";
    public static readonly string Natural = "\ue261";
    public static readonly string Sharp = "\ue262";
    public static readonly string DoubleSharp = "\ue263";
    public static readonly string DoubleFlat = "\ue264";
    public static readonly string TripleSharp = "\ue262 \ue263";
    public static readonly string TripleFlat = "\ue266";
    public static readonly string Dot = "\ue1e7";

    // Pauses
    public static readonly string Pause_1 = "\ue4e3";
    public static readonly string Pause_2 = "\ue4e4";
    public static readonly string Pause_4 = "\ue4e5";
    public static readonly string Pause_8 = "\ue4e6";
    public static readonly string Pause_16 = "\ue4e7";
    public static readonly string Pause_32 = "\ue4e8";

    // Tie
    public static readonly string Tie = "\ue551";

    public static float dpTOpx(float dp)
    {
        // 获取屏幕 DPI（dots per inch）
        float dpi = Screen.dpi;

        // 计算缩放因子
        float scaleFactor = dpi / 160f;

        // 应用维度转换
        float pixels = dp * scaleFactor;
        return pixels;
        //Resources r = context.Resources;
        //return TypedValue.ApplyDimension(ComplexUnitType.Dip, dp, r.DisplayMetrics);
    }

    public static float pxTOdp(float px)
    {
        return px;
        //Resources r = context.Resources;
        //float tmp = TypedValue.ApplyDimension(ComplexUnitType.Dip, 1, r.DisplayMetrics);
        //return px / tmp;
    }

    public static int DistanceBetweenNotes(FM_BaseNote n1, FM_BaseNote n2)
    {
        if (n1.stave != n2.stave) return 10;
        return (n1.note - n2.note) + ((n1.octave - n2.octave) * 7);
    }

    public static float Slope(float x1, float y1, float x2, float y2)
    {
        return Slope(0.2f, x1, y1, x2, y2);
    }

    public static float Slope(float maxSlope, float x1, float y1, float x2, float y2)
    {
        float ret = (y2 - y1) / (x2 - x1);
        if (ret > maxSlope) ret = maxSlope;
        if (ret < -maxSlope) ret = -maxSlope;
        return ret;
    }

    public static float GetY2(float slope, float x1, float y1, float x2)
    {
        return y1 + slope * (x2 - x1);
    }

    public static int KeyCount(string key)
    {
        key = key.Replace("\\", "").Replace("\"", "").Replace("[", "").Replace("]", "").ToLower().Trim();
        string[] s = key.Split(',');
        return s.Length;
    }

    public static int KeyToNote(string key)
    {
        return KeyToNote(key, 0);
    }

    public static int KeyToNote(string key, int index)
    {
        key = key.Replace("\\", "").Replace("\"", "").Replace("[", "").Replace("]", "").ToLower().Trim();
        string[] s = key.Split(',');
        key = s[index];
        if (key.StartsWith("do")) return FM_NoteValue.DO;
        if (key.StartsWith("re")) return FM_NoteValue.RE;
        if (key.StartsWith("mi")) return FM_NoteValue.MI;
        if (key.StartsWith("fa")) return FM_NoteValue.FA;
        if (key.StartsWith("sol")) return FM_NoteValue.SOL;
        if (key.StartsWith("la")) return FM_NoteValue.LA;
        if (key.StartsWith("si")) return FM_NoteValue.SI;

        if (key.StartsWith("c")) return FM_NoteValue.DO;
        if (key.StartsWith("d")) return FM_NoteValue.RE;
        if (key.StartsWith("e")) return FM_NoteValue.MI;
        if (key.StartsWith("f")) return FM_NoteValue.FA;
        if (key.StartsWith("g")) return FM_NoteValue.SOL;
        if (key.StartsWith("a")) return FM_NoteValue.LA;
        if (key.StartsWith("b")) return FM_NoteValue.SI;

        if (key.StartsWith("r")) return FM_NoteValue.REST;
        return FM_NoteValue.DO;
    }

    public static int KeyToOctave(string key)
    {
        return KeyToOctave(key, 0);
    }

    public static int KeyToOctave(string key, int index)
    {
        key = key.Replace("\\", "").Replace("\"", "").Replace("[", "").Replace("]", "").ToLower().Trim();
        string[] s = key.Split(',');
        key = s[index].Trim();
        if (key.Equals("r")) return 0;
        return int.Parse(key.Substring(key.Length - 1));
    }

    public static FM_DurationValue KeyToDuration(string key, int pos)
    {
        key = key.Replace("\\", "").Replace("\"", "").Replace("[", "").Replace("]", "").ToLower().Trim();
        string[] s = key.Split(',');
        key = s[pos].Trim();
        if (key.Equals("w")) return FM_DurationValue.NOTE_WHOLE;
        if (key.Equals("wr")) return FM_DurationValue.NOTE_WHOLE;
        if (key.Equals("wd")) return FM_DurationValue.NOTE_WHOLE_D;
        if (key.Equals("wdr")) return FM_DurationValue.NOTE_WHOLE_D;
        if (key.Equals("h")) return FM_DurationValue.NOTE_HALF;
        if (key.Equals("hr")) return FM_DurationValue.NOTE_HALF;
        if (key.Equals("hd")) return FM_DurationValue.NOTE_HALF_D;
        if (key.Equals("hdr")) return FM_DurationValue.NOTE_HALF_D;
        if (key.Equals("q")) return FM_DurationValue.NOTE_QUARTER;
        if (key.Equals("qr")) return FM_DurationValue.NOTE_QUARTER;
        if (key.Equals("qd")) return FM_DurationValue.NOTE_QUARTER_D;
        if (key.Equals("qdr")) return FM_DurationValue.NOTE_QUARTER_D;
        if (key.Equals("8")) return FM_DurationValue.NOTE_EIGHTH;
        if (key.Equals("8r")) return FM_DurationValue.NOTE_EIGHTH;
        if (key.Equals("8d")) return FM_DurationValue.NOTE_EIGHTH_D;
        if (key.Equals("8dr")) return FM_DurationValue.NOTE_EIGHTH_D;
        if (key.Equals("16")) return FM_DurationValue.NOTE_SIXTEENTH;
        if (key.Equals("16r")) return FM_DurationValue.NOTE_SIXTEENTH;
        if (key.Equals("16d")) return FM_DurationValue.NOTE_SIXTEENTH_D;
        if (key.Equals("16dr")) return FM_DurationValue.NOTE_SIXTEENTH_D;
        if (key.Equals("32")) return FM_DurationValue.NOTE_THIRTY_SECOND;
        if (key.Equals("32r")) return FM_DurationValue.NOTE_THIRTY_SECOND;
        if (key.Equals("32d")) return FM_DurationValue.NOTE_THIRTY_SECOND_D;
        if (key.Equals("32dr")) return FM_DurationValue.NOTE_THIRTY_SECOND_D;
        return FM_DurationValue.NOTE_WHOLE;
    }

    public static int KeyToAccidental(string key, int pos)
    {
        key = key.Replace("\\", "").Replace("\"", "").Replace("[", "").Replace("]", "").ToLower().Trim();
        string[] s = key.Split(',');
        key = s[pos].Trim().Substring(1);
        int courtesy = 0;
        if (key.Contains("(")) courtesy = FM_Accidental.Courtesy;
        if (key.Contains("###")) return courtesy + FM_Accidental.TripleSharp;
        if (key.Contains("##")) return courtesy + FM_Accidental.DoubleSharp;
        if (key.Contains("#")) return courtesy + FM_Accidental.Sharp;
        if (key.Contains("bbb")) return courtesy + FM_Accidental.TripleFlat;
        if (key.Contains("bb")) return courtesy + FM_Accidental.DoubleFlat;
        if (key.Contains("b")) return courtesy + FM_Accidental.Flat;
        if (key.Contains("n")) return courtesy + FM_Accidental.Natural;
        return FM_Accidental.None;
    }

    public static bool KeyToStem(string key, int pos)
    {
        key = key.Replace("\\", "").Replace("\"", "").Replace("[", "").Replace("]", "").ToLower().Trim();
        string[] s = key.Split(',');
        key = s[pos].Trim();
        return key.Equals("up");
    }

    public static string KeyToElement(string key, int pos)
    {
        key = key.Replace("\\", "").Replace("\"", "").Replace("[", "").Replace("]", "").ToLower().Trim();
        string[] s = key.Split(',');
        key = s[pos].Trim();
        return key;
    }
    public static FM_KeySignatureValue StringToKeySignature(string s)
    {
        s = s.ToLower().Trim();
        if (s == "do") return FM_KeySignatureValue.DO;
        if (s == "fa") return FM_KeySignatureValue.FA;
        if (s == "sib") return FM_KeySignatureValue.SIb;
        if (s == "mib") return FM_KeySignatureValue.MIb;
        if (s == "lab") return FM_KeySignatureValue.LAb;
        if (s == "reb") return FM_KeySignatureValue.REb;
        if (s == "solb") return FM_KeySignatureValue.SOLb;
        if (s == "dob") return FM_KeySignatureValue.DOb;
        if (s == "sol") return FM_KeySignatureValue.SOL;
        if (s == "re") return FM_KeySignatureValue.RE;
        if (s == "la") return FM_KeySignatureValue.LA;
        if (s == "mi") return FM_KeySignatureValue.MI;
        if (s == "si") return FM_KeySignatureValue.SI;
        if (s == "fa#") return FM_KeySignatureValue.FAsharp;
        if (s == "do#") return FM_KeySignatureValue.DOsharp;
        if (s == "lam") return FM_KeySignatureValue.LAm;
        if (s == "rem") return FM_KeySignatureValue.REm;
        if (s == "solm") return FM_KeySignatureValue.SOLm;
        if (s == "dom") return FM_KeySignatureValue.DOm;
        if (s == "fam") return FM_KeySignatureValue.FAm;
        if (s == "sibm") return FM_KeySignatureValue.SIbm;
        if (s == "mibm") return FM_KeySignatureValue.MIbm;
        if (s == "labm") return FM_KeySignatureValue.LAbm;
        if (s == "mim") return FM_KeySignatureValue.MIm;
        if (s == "sim") return FM_KeySignatureValue.SIm;
        if (s == "fa#m") return FM_KeySignatureValue.FAsharpm;
        if (s == "do#m") return FM_KeySignatureValue.DOsharpm;
        if (s == "sol#m") return FM_KeySignatureValue.SOLsharpm;
        if (s == "re#m") return FM_KeySignatureValue.REsharpm;
        if (s == "la#m") return FM_KeySignatureValue.LAsharpm;
        return FM_KeySignatureValue.DO;
    }

    public static float GetScaleFactor()
    {
        // 获取屏幕 DPI（dots per inch）
        float dpi = Screen.dpi;

        // 计算缩放因子
        float scaleFactor = dpi / 160f;

        return scaleFactor;
    }

    public static void AdjustFont(FM_Score Score, string text, float stave_lines_cnt)
    {
        // 计算缩放因子
        float scaleFactor = GetScaleFactor();

        if (stave_lines_cnt == 1)
        {
            Score.Font.TextSize = 26 * scaleFactor;
        }
        else if (stave_lines_cnt > 1)
        {
            Score.Font.TextSize = 26 * scaleFactor;
        }
        else
        {
            Score.Font.TextSize = 26 * scaleFactor;
        }
        //if (text == "")
        //{
        //    Score.Font.TextSize = 10;
        //    return;
        //}
        //float height = Score.GetDistanceBetweenStaveLines() * stave_lines_cnt + dpTOpx(1);
        //Score.Font.TextSize = 100f;
        //Rect bounds = new Rect();
        //Score.Font.GetTextBounds(text, 0, text.Length, bounds);
        //Score.Font.TextSize = 100f * height / bounds.height;
    }

    public string ConvertNote(string note, FM_NotationSystem notationSystem)
    {
        note = note.ToLower().Trim();
        int n = 0;
        if (note == "c" || note == "do" || note == "ha") n = 1;
        if (n == 0 && (note == "d" || note == "re" || note == "ni")) n = 2;
        if (n == 0 && (note == "e" || note == "mi" || note == "ho")) n = 3;
        if (n == 0 && (note == "f" || note == "fa" || note == "he")) n = 4;
        if (n == 0 && (note == "g" || note == "sol" || note == "to")) n = 5;
        if (n == 0 && (note == "a" || note == "la" || note == "i")) n = 6;
        if (n == 0 && (note == "b" || note == "h" || note == "si" || note == "ro")) n = 7;
        if (notationSystem == FM_NotationSystem.ENGLISH)
        {
            if (n == 1) return "c";
            if (n == 2) return "d";
            if (n == 3) return "e";
            if (n == 4) return "f";
            if (n == 5) return "g";
            if (n == 6) return "a";
            if (n == 7) return "b";
        }
        if (notationSystem == FM_NotationSystem.GERMAN)
        {
            if (n == 1) return "c";
            if (n == 2) return "d";
            if (n == 3) return "e";
            if (n == 4) return "f";
            if (n == 5) return "g";
            if (n == 6) return "a";
            if (n == 7) return "h";
        }
        if (notationSystem == FM_NotationSystem.ITALIAN)
        {
            if (n == 1) return "do";
            if (n == 2) return "re";
            if (n == 3) return "mi";
            if (n == 4) return "fa";
            if (n == 5) return "sol";
            if (n == 6) return "la";
            if (n == 7) return "si";
        }
        if (notationSystem == FM_NotationSystem.JAPANESE)
        {
            if (n == 1) return "ha";
            if (n == 2) return "ni";
            if (n == 3) return "ho";
            if (n == 4) return "he";
            if (n == 5) return "to";
            if (n == 6) return "i";
            if (n == 7) return "ro";
        }
        return "";
    }

    //[FM_TimeSignatureValue]
    public static FM_TimeSignatureValue GetTimeSignatureN(string s)
    {
        var ret = FM_TimeSignatureValue.None;
        if (s.StartsWith("2")) ret = FM_TimeSignatureValue._2;
        if (s.StartsWith("3")) ret = FM_TimeSignatureValue._3;
        if (s.StartsWith("4")) ret = FM_TimeSignatureValue._4;
        if (s.StartsWith("5")) ret = FM_TimeSignatureValue._5;
        if (s.StartsWith("6")) ret = FM_TimeSignatureValue._6;
        if (s.StartsWith("7")) ret = FM_TimeSignatureValue._7;
        if (s.StartsWith("8")) ret = FM_TimeSignatureValue._8;
        if (s.StartsWith("9")) ret = FM_TimeSignatureValue._9;
        return ret;
    }

    public static FM_TimeSignatureValue GetTimeSignatureD(string s)
    {
        var ret = FM_TimeSignatureValue.None;
        if (s.EndsWith("2")) ret = FM_TimeSignatureValue._2;
        if (s.EndsWith("3")) ret = FM_TimeSignatureValue._3;
        if (s.EndsWith("4")) ret = FM_TimeSignatureValue._4;
        if (s.EndsWith("5")) ret = FM_TimeSignatureValue._5;
        if (s.EndsWith("6")) ret = FM_TimeSignatureValue._6;
        if (s.EndsWith("7")) ret = FM_TimeSignatureValue._7;
        if (s.EndsWith("8")) ret = FM_TimeSignatureValue._8;
        if (s.EndsWith("9")) ret = FM_TimeSignatureValue._9;
        return ret;
    }

    public static float GetDurationMs(FM_DurationValue duration)
    {
        if (duration == FM_DurationValue.NOTE_WHOLE) return 4;
        if (duration == FM_DurationValue.NOTE_WHOLE_D) return 6;
        if (duration == FM_DurationValue.NOTE_HALF) return 2;
        if (duration == FM_DurationValue.NOTE_HALF_D) return 3;
        if (duration == FM_DurationValue.NOTE_QUARTER) return 1;
        if (duration == FM_DurationValue.NOTE_QUARTER_D) return 1.5f;
        if (duration == FM_DurationValue.NOTE_EIGHTH) return 0.5f;
        if (duration == FM_DurationValue.NOTE_EIGHTH_D) return 0.5f + 0.25f;
        if (duration == FM_DurationValue.NOTE_SIXTEENTH) return 0.25f;
        if (duration == FM_DurationValue.NOTE_SIXTEENTH_D) return 0.25f + 1 / 8f;
        if (duration == FM_DurationValue.NOTE_THIRTY_SECOND) return 1 / 8f;
        if (duration == FM_DurationValue.NOTE_THIRTY_SECOND_D) return 1 / 8f + 1 / 16f;
        return 0;
    }

    public static string TranslateKey(string key, FM_NotationSystem system)
    {
        string[] english = { "C", "D", "E", "F", "G", "A", "B" };
        string[] german = { "C", "D", "E", "F", "G", "A", "H" };
        string[] italian = { "DO", "RE", "MI", "FA", "SOL", "LA", "SI" };
        string[] japanese = { "ハ", "ニ", "ホ", "ヘ", "ト", "イ", "ロ" };
        string[] korean = { "다", "라", "바", "아", "사", "가", "나" };
        string[] indian = { "सा", "रे", "ग", "म", "प", "ध", "नि" };
        string[] cyrillic = { "до", "ре", "ми", "фа", "соль", "ля", "си" };

        bool isItalian = false;
        foreach (string s in italian)
        {
            if (key.Contains(s))
            {
                isItalian = true;
                break;
            }
        }
        for (int i = 0; i < english.Length; i++)
        {
            string replacement = "";
            if (system == FM_NotationSystem.ENGLISH) replacement = english[i];
            if (system == FM_NotationSystem.GERMAN) replacement = german[i];
            if (system == FM_NotationSystem.ITALIAN) replacement = italian[i];
            if (system == FM_NotationSystem.JAPANESE) replacement = japanese[i];
            if (system == FM_NotationSystem.KOREAN) replacement = korean[i];
            if (system == FM_NotationSystem.INDIAN) replacement = indian[i];
            if (system == FM_NotationSystem.CYRILLIC) replacement = cyrillic[i];

            if (isItalian) key = key.Replace(italian[i], replacement);
            else
            {
                key = key.Replace(english[i], replacement);
                key = key.Replace(german[i], replacement);
                key = key.Replace(japanese[i], replacement);
                key = key.Replace(korean[i], replacement);
                key = key.Replace(cyrillic[i], replacement);
            }
        }
        return key;
    }

}